const fragment = /* wgsl */ `
in vec2 vTextureCoord;
in vec4 vColor;

uniform sampler2D uTexture;
uniform vec3 gainRGB;
uniform int auto;
uniform float expousre;
uniform float hue;
uniform float brightness;
uniform float highlight;
uniform float shadow;
uniform float contrast;
uniform float saturate;
uniform float width;
uniform float height;

vec3 rgbToHsv( vec3 rgb )
{
    float h = 0.0;
    float s = 0.0;
    float v = 0.0;
    float r = rgb[0];
    float g = rgb[1];
    float b = rgb[2];

    float max = max(max(r, g), b);
    float min = min(min(r, g), b);
    v = max / 255.0;
    if (max == 0.0) {
      s = 0.0;
    } else {
      s = 1.0 - min / max;
    }
    if (max == min) {
      h = 0.0;
    } else if (max == r && g >= b) {
      h = 60.0 * ((g - b) / (max - min)) + 0.0;
    } else if (max == r && g < b) {
      h = 60.0 * ((g - b) / (max - min)) + 360.0;
    } else if (max == g) {
      h = 60.0 * ((b - r) / (max - min)) + 120.0;
    } else if (max == b) {
      h = 60.0 * ((r - g) / (max - min)) + 240.0;
    }
    int intH = int(h);
  return vec3(intH, s, v);
}
vec3 hsvToRgb(vec3 hsv) {
  float h = hsv[0];
  float s = max(0.0, hsv[1]);
  float v = hsv[2];
  float r = 0.0;
  float g = 0.0;
  float b = 0.0;
  int i = int(mod(h / 60.0, 6.0));
  float f = h / 60.0 - float(i);
  float p = v * (1.0 - s);
  float q = v * (1.0 - f * s);
  float t = v * (1.0 - (1.0 - f) * s);
  if(i == 0) {
    r = v;
    g = t;
    b = p;
  }
  if (i == 1) {
    r = q;
    g = v;
    b = p;
  }
  if (i == 2) {
    r = p;
    g = v;
    b = t;
  }
  if (i == 3) {
    r = p;
    g = q;
    b = v;
  }
  if (i == 4) {
    r = t;
    g = p;
    b = v;
  }
  if (i == 5) {
    r = v;
    g = p;
    b = q;
  }
  r = r * 255.0;
  g = g * 255.0;
  b = b * 255.0;
  return vec3(r, g, b);
}
float round(float num) {
  return floor(num + 0.5);
}
vec3 colorconstancy(vec3 rgb) {
  float r = min(round(gainRGB[0] * rgb[0]), 255.0);
  float g = min(round(gainRGB[1] * rgb[1]), 255.0);
  float b = min(round(gainRGB[2] * rgb[2]), 255.0);
  return vec3(r, g, b);
}
vec3 adjustHue(vec3 rgb) {
  if(hue == 0.0) return rgb;
  vec3 hsv = rgbToHsv(rgb);
  hsv[0] += hue;
  if (hsv[0] < 0.0) hsv[0] += 360.0;
  if (hsv[0] >= 360.0) hsv[0] -= 360.0;
  return hsvToRgb(hsv);
}
int getExpousreTableResult(float E, int v) {
  float gamma = pow(1.75, abs(E));
  if (E < 0.0) gamma = 1.0 / gamma;
  int num;
  if(E >= 0.0) {
    num = int(256.0 - 256.0 * pow((256.0 - float(v)) / 256.0, gamma));
  }else {
    num = int(260.0 - 260.0 * pow((260.0 - float(v)) / 260.0, gamma));
  }
  if (num < 0) num = 0;
  if (num > 255) num = 255;
  return num;
}
vec3 adjustExposure(vec3 rgb) {
  if(expousre == 0.0) return rgb;
  vec3 result = rgb;
  float E = expousre / 20.0;
  int tempE = int(E * 256.0);
  if (E > 0.0) {
    vec3 hsv = rgbToHsv(rgb);
    int v = int(hsv[2] * 255.0);
    if (hsv[1] != 0.0) {
      if (v <= 128) {
        hsv[1] = hsv[1] - (float(v * tempE) / pow(2.0, 10.0)) / 255.0;
      } else {
        hsv[1] = hsv[1] - (float((255 - v) * tempE) / pow(2.0, 10.0)) / 255.0;
      }
      hsv[2] = float(getExpousreTableResult(E, v)) / 255.0;
      vec3 resultRgb = hsvToRgb(hsv);
      result = resultRgb;
    }else {
      float num = float(getExpousreTableResult(E, v));
      result = vec3(num);
    }
  } else {
    float r = float(getExpousreTableResult(E, int(rgb.r)));
    float g = float(getExpousreTableResult(E, int(rgb.g)));
    float b = float(getExpousreTableResult(E, int(rgb.b)));
    result = vec3(r, g, b);
  }
  return result;
}
float getAdjustBrightnessTableResult( float i, float gamma, float gamma1, int la) {
  float lR = round(255.0 * pow((255.0 - 255.0 * pow((255.0 - i) / 255.0, gamma)) / 255.0, gamma1));
  if (lR < 0.0) lR = 0.0;
  if (lR > 255.0) lR = 255.0;
  if (lR <= 128.0) {
    lR = lR + (((lR - 128.0) * lR * float(la)) / pow(2.0, 20.0));
    if (lR < 0.0) lR = 0.0;
    if (lR > 255.0) lR = 255.0;
  } else {
    lR = lR + (((lR - 128.0) * (255.0 - lR) * float(la)) / pow(2.0, 20.0));
    if (lR < 0.0) lR = 0.0;
    if (lR > 255.0) lR = 255.0;
  }
  return lR;
}
vec3 adjustBrightnessContrast( vec3 rgb) {
  float B = brightness;
  float C = contrast;
  if( B==0.0 && C==0.0){
    return rgb;
  }
  float absB = abs(B);
  float tempB = absB / 50.0;
  float gamma, gamma1;
  if (absB <= 50.0) {
    gamma = 0.76 * tempB + 1.0;
    gamma1 = 0.12 * tempB + 1.0;
  } else if (absB <= 100.0) {
    gamma = 0.94 * tempB + 0.82;
    if (B < 0.0) {
      gamma1 = 0.01 * tempB + 1.11;
    } else {
      gamma1 = 0.07 * tempB + 1.05;
    }
  } else {
    gamma = 1.8 * tempB - 0.9;
    if (B < 0.0) {
      gamma1 = 0.005 * tempB + 1.12;
    } else {
      gamma1 = 0.18 * tempB + 0.83;
    }
  }
  if (B < 0.0) {
    gamma = 1.0 / gamma;
    gamma1 = 1.0 / gamma1;
  }
  int la = int((C / 100.0) * 0.006 * (1.0 * pow(2.0, 20.0)));
  return vec3(getAdjustBrightnessTableResult(rgb.r,gamma,gamma1,la),getAdjustBrightnessTableResult(rgb.g,gamma,gamma1,la),getAdjustBrightnessTableResult(rgb.b,gamma,gamma1,la));
}
int getTableH(int i, float H) {
  int result = i;
  if (H > 0.0) {
    float k = 2.0572 * H * H + 2.34 * H + 0.0172;
    float b = 1.0 - k / 2.0;
    if(i < 128) {
      result = i;
    }else {
      int num = i - 128;
      float j = (float(num) + 128.0) / 255.0;
      if(i == 255) j = 1.0;
      float v = 255.0 * (1.0 - 0.5 * pow((1.0 - j) * 2.0, k * j + b)) + 0.5;
      if (v < 0.0) v = 0.0;
      if(v > 255.0) v = 255.0;
      result = int(v);
    }
  }else {
    float k = 7.67 * H;
    float c = 1.0 - k * 0.0784;
    if(i < 128) {
      result = i;
    }else {
      int num = i - 128;
      float j = (float(num) + 128.0) / 255.0;
      if(i == 255) j = 1.0;
      float v = 255.0 * (1.0 - 0.5 * pow((1.0 - j) * 2.0, k * pow(j - 0.78, 2.0) + c)) + 0.5;
      if (v < 0.0) v = 0.0;
      if (v > 255.0) v = 255.0;
      result = int(v);
    }
  }
  return result;
}
int getTableS(int i, float S) {
  int result = i;
  if(S >= 0.0) {
    float k = 6.8587 * S;
    float c = 1.0 - 0.5 * S;
    if(i < 128) {
      float j = float(i) / 255.0;
      float v = 127.5 * pow(j * 2.0, k * pow(j - 0.23, 2.0) + c) + 0.5;
      if (v < 0.0) v = 0.0;
      if (v > 255.0) v = 255.0;
      result = int(v);
    } else {
      result = i;
    }
  } else {
    float k = 5.7143 * S * S - 4.3 * S + 0.0477;
    float c = 1.0 - k * 0.0025;
    float j = float(i) / 255.0;
    float v = 127.5 * pow(j * 2.0, k * pow(j - 0.55, 2.0) + c) + 0.5;
    if (v < 0.0) v = 0.0;
    if (v > 255.0) v = 255.0;
    if(i < 128) {
      result = int(v);
    } else {
      result = i;
    }
  }
  return result;
}
int getTableB(int i, float B) {
  int result = i;
  // if (B > 0.0) {
  //   float k = 1.9642 * B * B + 1.4688 * B + 0.0267;
  //   float j = i / 255.0;
  //   int v = int(255.0 * (1.0 - pow(1.0 - j, k * j * j + 1.0)) + 0.5);
  //   if (v < 0) v = 0;
  //   if (v > 255) v = 255;
  //   result = float(v);
  // } else {
    float k = -1.69 * B;
    float c = 1.0 - k * 0.3025;
    if(i < 20) {
      result = i;
    } else if(i >= 20 && i < 256) {
      float j = float(i) / 255.0;
      float v = 255.0 * (1.0 - 0.92 * pow((1.0 - j) * 1.087, k * pow(j - 0.63, 2.0) + c)) + 0.5;
      if (v < 0.0) v = 0.0;
      if (v > 255.00) v = 255.0;
      result = int(v);
    }
  // }
  return result;
}
int getTableD(int i, float D) {
  int result = i;
  // if (D >= 0.0) {
    float k = 1.52 * D;
    float c = 1.0 - k * 0.3025;
    float j = float(i) / 255.0;
    float v = 255.0 * pow(j, k * pow(j - 0.45, 2.0) + c) + 0.5;
    if (v < 0.0) v = 0.0;
    if (v > 255.0) v = 255.0;
    result = int(v);
  // } else {
  //   if (D < -0.75) {
  //     float k = 0.9796 * D * D - 0.6786 * D - 0.0061;
  //     float c = 1.0 - k * 0.04;
  //     float k1 = -k * 8.2;
  //     float c1 = k * 1.44 + c - k1 * 0.0025;
  //     if(i < 89.0) {
  //       float j = i / 255.0;
  //       int v = int(255.0 * pow(j, k1 * pow(j - 0.05, 2.0) + c1) + 0.5);
  //       if (v < 0) v = 0;
  //       if (v > 255) v = 255;
  //       result = float(v);
  //     } else if(i >= 89.0 && i < 256.0) {
  //       float j = i / 255.0;
  //       int v = int(255.0 * pow(j, k * pow(j - 1.2, 2.0) + c) + 0.5);
  //       if (v < 0) v = 0;
  //       if (v > 255) v = 255;
  //       result = float(v);
  //     }
  //   } else {
  //     float k = 0.9796 * D * D - 0.6786 * D - 0.0061;
  //     float c = 1.0 - k * 0.04;
  //     float j = i / 255.0;
  //     int v = int(255.0 * pow(j, k * pow(j - 1.2, 2.0) + c) + 0.5);
  //     if (v < 0) v = 0;
  //     if (v > 255) v = 255;
  //     result = float(v);
  //   }
  // }
  return result;
}
int getTableHB(int i, float B, float D) {
  int result = i;
  // if (B < 0.0 && D > 0.0) {
  //   float v = getTableB(i, B) + getTableD(i, D) - i;
  //   if (v < 0.0) v = 0.0;
  //   if (v > 255.0) v = 255.0;
  //   result = v;
  // } else if (B > 0.0 && D > 0.0) {
  //   if(i >= 0.0 && i < 25.0) {
  //     result = min(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //   } else if( i >= 25.0 && i < 128.0) {
  //     float k = max(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //     float b = min(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //     int v = int(((k - b) * i) / 102.0 + b - ((k - b) * 25.0) / 102.0 + 0.5);
  //     if (v < 0) v = 0;
  //     if (v > 255) v = 255;
  //     result = float(v);
  //   } else if( i >= 128.0 && i < 256.0) {
  //     result = max(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //   }
  // } else if (B < 0.0 && D < 0.0) {
  //   if( i >= 0.0 && i < 127.0) {
  //     result = min(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //   } else if(i >= 127.0 && i < 231.0) {
  //     float k = max(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //     float b = min(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //     int v = int(
  //       ((k - b) * i) / 103.0 + b - ((k - b) * 127.0) / 103.0 + 0.5
  //     );
  //     if (v < 0) v = 0;
  //     if (v > 255) v = 255;
  //     result = float(v);
  //   } else if(i>231.0 && i < 256.0) {
  //     result = max(getTableB(getTableD(i, D), B), getTableD(getTableB(i, B), D));
  //   }
  // } else {
    result = int((getTableB(getTableD(i, D), B) + getTableD(getTableB(i, B), D)) / int(pow(2.0, 1.0)));
  // }
  return result;
}
int getTableHBDS(int i, float H, float S, float B, float D) {
  int result = i;
  result = getTableHB(getTableS(getTableH(i, H), S), B, D);
  // result = getTableH(i, H);
  // result = getTableS(i, S);
  // result = getTableHB(i, B, D);
  // result = int(255.0 / 255.0);
  // result = int(1.0);
  return result;
}
vec3 adjustHighlightBrightDarkShadow(vec3 rgb) {
  if(highlight == 0.0 && shadow == 0.0) return rgb;
  float H = highlight / 100.0;
  float S = shadow / 100.0;
  float B = 0.0;
  float D = 0.0;
  float r = float(getTableHBDS(int(rgb.r), H, S, B, D));
  float g = float(getTableHBDS(int(rgb.g), H, S, B, D));
  float b = float(getTableHBDS(int(rgb.b), H, S, B, D));
  return vec3(r, g, b);
}
vec3 adjustSaturate(vec3 rgb, float i) {
  if(saturate == 0.0) return rgb;
  vec3 result = vec3(rgb);
  float increment = saturate / 100.0;
  float delta;
  // if(i == 7204.0) {
  //   delta = 0.0;
  // };
  float rgbMax = max(rgb.r, max(rgb.g, rgb.b));
  float rgbMin = min(rgb.r, min(rgb.g, rgb.b));
  delta = (rgbMax - rgbMin) / 255.0;
  // 加了个新的作对比，使用float对比因为精度问题导致不相等
  int newDelta = int(rgbMax - rgbMin);
  if (newDelta == 0) {
    return rgb;
  }
  float value = (rgbMax + rgbMin) / 255.0;
  float L = value / 2.0;
  float S;
  float alpha;
  if (L < 0.5) {
    S = delta / value;
  } else {
    S = delta / (2.0 - value);
  }
  if (increment >= 0.0) {
    if (increment + S >= 1.0) {
      alpha = S;
    } else {
      alpha = 1.0 - increment;
    }
    alpha = 1.0 / alpha - 1.0;
    result.r = float(int(rgb.r + (rgb.r - L * 255.0) * alpha));
    result.g = float(int(rgb.g + (rgb.g - L * 255.0) * alpha));
    result.b = float(int(rgb.b + (rgb.b - L * 255.0) * alpha));
  } else {
    alpha = increment;
    result.r = float(int(L * 255.0 + (rgb.r - L * 255.0) * (1.0 + alpha)));
    result.g = float(int(L * 255.0 + (rgb.g - L * 255.0) * (1.0 + alpha)));
    result.b = float(int(L * 255.0 + (rgb.b - L * 255.0) * (1.0 + alpha)));
  }
  if(result.r < 0.0) result.r = 0.0;
  if(result.r > 255.0) result.r = 255.0;
  if(result.g < 0.0) result.g = 0.0;
  if(result.g > 255.0) result.g = 255.0;
  if(result.b < 0.0) result.b = 0.0;
  if(result.b > 255.0) result.b = 255.0;
  return result;
}

void main(void)
{
    vec4 texelValue = texture2D(uTexture, vTextureCoord);
    vec3 result = vec3(texelValue.r, texelValue.g, texelValue.b)  * vec3(255.0);
    vec3 rgb = vec3(texelValue.r, texelValue.g, texelValue.b) * vec3(255.0);
    if (auto == 1) {
      result = colorconstancy(rgb);
    }
    result = adjustBrightnessContrast(result);
    result = adjustExposure(result);
    result = adjustHighlightBrightDarkShadow(result);
    result = adjustHue(result);
    result = adjustSaturate(result, vTextureCoord.x * width + vTextureCoord.y);
    gl_FragColor = vec4(result / vec3(255.0), 1.0);
}
`
export default fragment
